import Notice,{Position,NoticeType,CloseFunction} from './Notice';
import {getUid} from '../../../util/common';
import {PlainObject} from '../../../../types';
import 'animate.css';
import {rootContainerVue,renders} from '../../js/pc/rootContainer';
//region 定义接口
/**
 * 传给api的选项
 * @property {string} title			标题
 * @property {string} [content]		内容
 * @property {NoticeType} [type]	轻提示类型
 * @property {number} [width]		宽度
 * @property {number} [duration]	显示时长, 0表示不限制
 * @property {Position} [position]	提示位置
 * @property {number} [max]			最大实例数, 0表示不限制
 * @property {number} [override]	替换最早的提示, 默认true
 */
export interface passOptions{
	title:string,
	content?:string,
	type?:NoticeType,
	width?:number,
	duration?:number,
	position?:Position,
	max?:number,
	override?:boolean,
}
/**
 * 传给Notice组件的选项
 */
export interface Options extends passOptions{
	uid:string,
	onClose?:CloseFunction,
	position:Position,
	max:number,
}
/**
 * 返回值类型
 */
export type ResultType=Promise<void>&{close:() => void};
/**
 * 提示方法
 * @param {passOptions|string} opt 选项
 * @return {ResultType} 关闭后resolve的promise
 */
export interface AlertFunction{
	(opt:passOptions|string):ResultType
}
/**
 * 定义接口
 * @property {AlertFunction} show		不预定义类型的提示
 * @property {AlertFunction} info		普通提示
 * @property {AlertFunction} success	成功提示
 * @property {AlertFunction} warning	警告提示
 * @property {AlertFunction} error		错误提示
 */
export interface NoticeApi{
	show:AlertFunction,
	info:AlertFunction,
	success:AlertFunction,
	warning:AlertFunction,
	error:AlertFunction,
}
//endregion
//弹窗实例
const allContainer={
	left:[] as Array<Options>,
	center:[] as Array<Options>,
	right:[] as Array<Options>,
};
const count={
	left:0,
	center:0,
	right:0,
};
const positions:Array<Position>=['left','center','right'];
const resolves:Array<Function>=[];
let globalPromise:Promise<void>=Promise.resolve();
//渲染函数
renders.push(function(h){
	return h('div',{
		staticClass:'lexmis-NoticeContainer',
	},positions.map((position) => {
		return h('transition-group',{
			staticClass:`lexmis_${position}`,
			props:{
				tag:'div'
			},
			on:{
				'after-enter':() => {
					const resolve=resolves.pop();
					if(resolve){
						resolve();
					}
				},
				'enter-cancelled':() => {
					const resolve=resolves.pop();
					if(resolve){
						resolve();
					}
				},
				'before-leave':(el:HTMLElement) => {
					const {top,left,right}=el.getBoundingClientRect();
					el.style.top=Math.round(top)+'px';
					if(position==='right'){
						// @ts-ignore
						el.style.right=this.$el.clientWidth-Math.round(right)+'px';
					}else{
						el.style.left=Math.round(left)+'px';
					}
				},
			},
			key:position,
		},allContainer[position].map((opt) => {
			return h(Notice,{
				props:opt,
				key:opt.uid,
			});
		}));
	}));
});
rootContainerVue.$forceUpdate();
//标准化选项
function normalizedOptions(opt:passOptions|string,extend?:PlainObject){
	if(typeof opt==='string'){
		opt={title:opt};
	}
	return Object.assign({
		uid:getUid(),
		position:'right',
		max:3,
		override:true,
	},opt,extend);
}
//不预定义类型的提示
function realShow(option:Options):ResultType{
	const container=allContainer[option.position];
	const addOption=() => {
		++count[option.position];
		const res:Promise<void>=new Promise((resolve) => {
			const promise:Promise<void>=globalPromise.then(() => {
				container.unshift(option);
				rootContainerVue.$forceUpdate();
				return new Promise((resolve) => {
					resolves.push(resolve);
				});
			});
			option.onClose=() => {
				promise.then(() => {
					const pos=container.indexOf(option);
					if(pos!==-1){
						container.splice(pos,1);
					}
					--count[option.position];
					rootContainerVue.$forceUpdate();
					resolve();
				});
			};
			globalPromise=promise;
		});
		return Object.assign(res,{
			close:option.onClose!,
		});
	};
	if(option.max>=1&&count[option.position]>=option.max){
		if(option.override){
			globalPromise.then(() => {
				container.pop()!.onClose!();
			});
			return addOption();
		}else{
			return Object.assign(
				Promise.reject(new Error(`轻提示达到最大个数${option.max}!`)),{
					close(){},
				}
			);
		}
	}else{
		return addOption();
	}
}
function show(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt));
}
function info(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'info',
	}));
}
function success(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'success',
	}));
}
function warning(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'warning',
	}));
}
function error(opt:passOptions|string):ResultType{
	return realShow(normalizedOptions(opt,{
		type:'error',
	}));
}
export default Object.assign(Notice,{
	show,
	info,
	success,
	warning,
	error,
}) as (NoticeApi&typeof Notice);
